package com.demo.main.utils;

import java.lang.reflect.Field;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

public class JSONUtil {
    // 定义日期和时间格式器，用于格式化 LocalDate 和 LocalDateTime 对象
    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ISO_LOCAL_DATE;
    private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ISO_LOCAL_DATE_TIME;

    /**
     * 将 Map 转换为 JSON 字符串。
     *
     * @param map 要转换的 Map 对象
     * @return 转换后的 JSON 字符串
     */
    public static String mapToJson(Map<String, Object> map) {
        if (map == null) {
            return "null"; // 如果 map 为空，返回 "null"
        }
        return map.entrySet().stream()
                .map(entry -> {
                    String key = escapeString(entry.getKey()); // 转义键名
                    String value = valueToJson(entry.getValue()); // 转换值
                    return "\"" + key + "\":" + value; // 拼接成 JSON 格式的键值对
                })
                .collect(Collectors.joining(",", "{", "}")); // 将所有键值对用逗号连接，并加上花括号
    }

    /**
     * 将任意对象转换为 JSON 字符串。
     *
     * @param value 要转换的对象
     * @return 转换后的 JSON 字符串
     */
    private static String valueToJson(Object value) {
        if (value == null) {
            return "null"; // 如果值为空，返回 "null"
        } else if (value instanceof String) {
            return "\"" + escapeString((String) value) + "\""; // 如果是字符串，添加引号并转义特殊字符
        } else if (value instanceof Number || value instanceof Boolean) {
            return value.toString(); // 如果是数字或布尔值，直接转换为字符串
        } else if (value instanceof LocalDate) {
            return "\"" + ((LocalDate) value).format(DATE_FORMATTER) + "\""; // 如果是 LocalDate，格式化为字符串
        } else if (value instanceof LocalDateTime) {
            return "\"" + ((LocalDateTime) value).format(DATE_TIME_FORMATTER) + "\""; // 如果是 LocalDateTime，格式化为字符串
        } else if (value instanceof Map) {
            @SuppressWarnings("unchecked")
            Map<String, Object> mapValue = (Map<String, Object>) value; // 如果是 Map，递归调用 mapToJson
            return mapToJson(mapValue);
        } else if (value instanceof Iterable) {
            return iterableToJson((Iterable<?>) value); // 如果是 Iterable，调用 iterableToJson
        } else {
            // 处理普通对象
            return objectToJson(value); // 如果是其他对象，调用 objectToJson
        }
    }

    /**
     * 将普通对象转换为 JSON 字符串。
     *
     * @param obj 要转换的对象
     * @return 转换后的 JSON 字符串
     */
    public static String objectToJson(Object obj) {
        if (obj == null) {
            return "null"; // 如果对象为空，返回 "null"
        }
        Class<?> clazz = obj.getClass(); // 获取对象的类类型
        Map<String, Object> map = new LinkedHashMap<>(); // 使用 LinkedHashMap 保持字段顺序

        for (Field field : clazz.getDeclaredFields()) {
            field.setAccessible(true); // 设置字段可访问
            try {
                Object value = field.get(obj); // 获取字段值
                if (value != null) {  // 只添加非null值
                    map.put(field.getName(), value); // 将字段名和值放入 Map
                }
            } catch (IllegalAccessException e) {
                // 忽略无法访问的字段
            }
        }
        return mapToJson(map); // 调用 mapToJson 方法将 Map 转换为 JSON 字符串
    }

    /**
     * 将 Iterable 对象转换为 JSON 数组字符串。
     *
     * @param iterable 要转换的 Iterable 对象
     * @return 转换后的 JSON 数组字符串
     */
    private static String iterableToJson(Iterable<?> iterable) {
        return StreamSupport.stream(iterable.spliterator(), false) // 创建流
                .map(JSONUtil::valueToJson) // 将每个元素转换为 JSON 字符串
                .collect(Collectors.joining(",", "[", "]")); // 将所有元素用逗号连接，并加上方括号
    }

    /**
     * 转义字符串中的特殊字符。
     *
     * @param input 要转义的字符串
     * @return 转义后的字符串
     */
    private static String escapeString(String input) {
        if (input == null) {
            return ""; // 如果输入为空，返回空字符串
        }
        StringBuilder sb = new StringBuilder(); // 使用 StringBuilder 构建结果字符串
        for (char c : input.toCharArray()) {
            switch (c) {
                case '"':
                    sb.append("\\\"");
                    break; // 转义双引号
                case '\\':
                    sb.append("\\\\");
                    break; // 转义反斜杠
                case '\b':
                    sb.append("\\b");
                    break; // 转义退格符
                case '\f':
                    sb.append("\\f");
                    break; // 转义换页符
                case '\n':
                    sb.append("\\n");
                    break; // 转义换行符
                case '\r':
                    sb.append("\\r");
                    break; // 转义回车符
                case '\t':
                    sb.append("\\t");
                    break; // 转义制表符
                default:
                    sb.append(c); // 其他字符直接添加
            }
        }
        return sb.toString(); // 返回转义后的字符串
    }
}